/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ArcsPanel.java
 *
 * Created on Apr 17, 2009, 12:57:07 PM
 */
package view.panels.analytical;

import controller.Controller;
import controller.GraphController;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
import java.util.Vector;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import jgf.Attribute;
import jgf.IGraph;
import jgf.beans.ArcBean;
import jgf.beans.GraphBean;
import jgf.beans.NodeBean;
import jgf.exceptions.arc.ArcException;
import jgf.exceptions.arc.DuplicatedArcException;
import jgf.exceptions.arc.UnexistentArcException;
import jgf.exceptions.attribute.BadAttributeListException;
import jgf.exceptions.node.DuplicatedNodeException;
import jgf.exceptions.node.UnexistentNodeException;
import utils.JGSCommonTools;

/**
 *
 * @author Biddu
 */
public class ArcsPanel extends javax.swing.JPanel {

    private GraphBean graph;
    private DefaultTableModel tArcModel;
    private int rowcount = 0;
    private Integer fromComboCaptureVal;
    private Integer toComboCaptureVal;
    public static final String ARC_ATTRIBUTE = "cost";
    private final int ATTRIBUTE_ID = 1;
    private final int DELETE_ID = 2;
    private Integer selectedRowID;
    private TreeMap<Integer, ArcBean> arcRows = new TreeMap<Integer, ArcBean>();
    private TreeMap<String, Integer> arcAttributes = new TreeMap<String, Integer>();

    /** Creates new form ArcsPanel */
    public ArcsPanel() {
        initComponents();
    }

    public ArcsPanel(IGraph graph) {
        this.graph = new GraphBean(graph);
        initComponents();
        this.syncOnLoad();
        this.setTableProperties();
    }

    public JComboBox getFromNodeCB() {
        return this.fromNodeComboBox;
    }

    public JComboBox getToNodeCB() {
        return this.toNodeComboBox;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        createArcDialog = new javax.swing.JDialog();
        fromNodeLabel = new javax.swing.JLabel();
        toNodeLabel = new javax.swing.JLabel();
        arcDialogButton = new javax.swing.JButton();
        fromNodeComboBox = new javax.swing.JComboBox();
        toNodeComboBox = new javax.swing.JComboBox();
        attributeDialog = new javax.swing.JDialog();
        attributeDLabel = new javax.swing.JLabel();
        attributeDComboBox = new javax.swing.JComboBox();
        attributeDValueLabel = new javax.swing.JLabel();
        attributeDValueText = new javax.swing.JTextField();
        attrDialogButton = new javax.swing.JButton();
        arcButton = new javax.swing.JButton();
        arcScrollPanel = new javax.swing.JScrollPane();
        arcsTable = new javax.swing.JTable();

        createArcDialog.setModal(true);
        createArcDialog.getContentPane().setLayout(new java.awt.GridBagLayout());

        fromNodeLabel.setText("From Node");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 10);
        createArcDialog.getContentPane().add(fromNodeLabel, gridBagConstraints);

        toNodeLabel.setText("To Node");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 10);
        createArcDialog.getContentPane().add(toNodeLabel, gridBagConstraints);

        arcDialogButton.setText("Okay");
        arcDialogButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                arcDialogButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 8, 0);
        createArcDialog.getContentPane().add(arcDialogButton, gridBagConstraints);

        fromNodeComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                fromNodeComboBoxActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 30;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 7, 0);
        createArcDialog.getContentPane().add(fromNodeComboBox, gridBagConstraints);

        toNodeComboBox.setSelectedItem(null);
        toNodeComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                toNodeComboBoxActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 30;
        gridBagConstraints.insets = new java.awt.Insets(9, 0, 5, 0);
        createArcDialog.getContentPane().add(toNodeComboBox, gridBagConstraints);

        createArcDialog.pack();

        attributeDialog.setTitle("Attribute");
        attributeDialog.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        attributeDialog.setModal(true);
        attributeDialog.setName("Attribute"); // NOI18N
        attributeDialog.getContentPane().setLayout(new java.awt.GridBagLayout());

        attributeDLabel.setText("Attribute:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        attributeDialog.getContentPane().add(attributeDLabel, gridBagConstraints);

        attributeDComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "cost" }));
        attributeDComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                attributeDComboBoxActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        attributeDialog.getContentPane().add(attributeDComboBox, gridBagConstraints);

        attributeDValueLabel.setText("Attribute Value:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        attributeDialog.getContentPane().add(attributeDValueLabel, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 33;
        attributeDialog.getContentPane().add(attributeDValueText, gridBagConstraints);

        attrDialogButton.setText("Okay");
        attrDialogButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                attrDialogButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.ipadx = 18;
        attributeDialog.getContentPane().add(attrDialogButton, gridBagConstraints);

        setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.PAGE_AXIS));

        arcButton.setText("Create Arcs");
        arcButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                arcButtonActionPerformed(evt);
            }
        });
        add(arcButton);

        arcsTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "*", "Frome Node", "To Node", "Attributes", "Delete"
            }
        ));
        arcScrollPanel.setViewportView(arcsTable);

        add(arcScrollPanel);
    }// </editor-fold>//GEN-END:initComponents

    private void arcButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_arcButtonActionPerformed

        if (graph != null && graph.getNodes().size() > 1) {
            this.fromNodeComboBox.setSelectedItem(null);
            this.toNodeComboBox.setSelectedItem(null);            
            createArcDialog.setVisible(true);
        } else {
            JOptionPane.showMessageDialog(this, "here should be more than 1 Node to create an Arc");
        }
		
    }//GEN-LAST:event_arcButtonActionPerformed

    private void arcDialogButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_arcDialogButtonActionPerformed
     
		Object fromVal = fromNodeComboBox.getSelectedItem();
		Object toVal = toNodeComboBox.getSelectedItem();
		if (fromVal != null && toVal != null) {
			ArcBean arc = new ArcBean();
			Integer from = (Integer) fromVal;
			Integer to = (Integer) toVal;
			arc.setFromId(from);
			arc.setToId(to);
			GraphController gc = controller.getGraphController(graph.getID());
			try {
				gc.insertArc(arc);
			}catch (DuplicatedArcException ex) {
				System.err.println("DuplicatedArcException in ArcsPanel");
			  JOptionPane.showMessageDialog(createArcDialog,ex.getMessage());
			} catch (UnexistentNodeException ex) {
				System.err.println("UnexistentNodeException in ArcsPanel");
				JOptionPane.showMessageDialog(createArcDialog,ex.getMessage());
			} catch (DuplicatedNodeException ex) {
				System.err.println("DuplicatedNodeException in ArcsPanel");
				JOptionPane.showMessageDialog(createArcDialog,ex.getMessage());
			} catch (ArcException ex) {
				System.err.println("ArcException in ArcsPanel");
				JOptionPane.showMessageDialog(createArcDialog,ex.getMessage());
			}
			createArcDialog.setVisible(false);
		} else {
			JOptionPane.showMessageDialog(createArcDialog,
					" Please verify following: " +'\n'+
					" 'From Node' and 'To Node' is not empty" );
		}
        //Resets the view
        fromNodeComboBox.setSelectedItem(null);
        toNodeComboBox.setSelectedItem(null);
}//GEN-LAST:event_arcDialogButtonActionPerformed
    
    private void fromNodeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fromNodeComboBoxActionPerformed
        Vector nodeNames = new Vector();
        for (NodeBean node : graph.getNodes()) {
            if (fromNodeComboBox.getSelectedItem() == null) {
                nodeNames.add(node);
            } else {
                if ((Integer) fromNodeComboBox.getSelectedItem() != node.getId()) {
                    nodeNames.add(node);
                }
            }
        }
        toComboCaptureVal = (Integer) toNodeComboBox.getSelectedItem();
        toNodeComboBox.setModel(new DefaultComboBoxModel(nodeNames));
        toNodeComboBox.setSelectedItem(toComboCaptureVal);
    }//GEN-LAST:event_fromNodeComboBoxActionPerformed

    private void toNodeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_toNodeComboBoxActionPerformed
        Vector nodeNames = new Vector();
        for (NodeBean node : graph.getNodes()) {
            if (toNodeComboBox.getSelectedItem() == null) {
                nodeNames.add(node);
            } else {
                if ((Integer) toNodeComboBox.getSelectedItem() != node.getId()) {
                    nodeNames.add(node);
                }
            }
        }
        fromComboCaptureVal = (Integer) fromNodeComboBox.getSelectedItem();
        fromNodeComboBox.setModel(new DefaultComboBoxModel(nodeNames));
        fromNodeComboBox.setSelectedItem(fromComboCaptureVal);
}//GEN-LAST:event_toNodeComboBoxActionPerformed

    private void attrDialogButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_attrDialogButtonActionPerformed
        String attrVal = attributeDValueText.getText();
        if (JGSCommonTools.containsOnlyNumbers(attrVal)) {
            int val = (new Integer(attrVal)).intValue();
            attributeDialog.setVisible(false);
            ArcBean tempArc = arcRows.get(selectedRowID);
            if (attributeDComboBox.getSelectedItem() != null && tempArc.getAttribute(attributeDComboBox.getSelectedItem().toString()) != null) {
                tempArc.getAttribute(attributeDComboBox.getSelectedItem().toString()).setValue(val);
            }
            GraphController gc = controller.getGraphController(graph.getID());
			try {
				gc.updateArc(tempArc);
			} catch (UnexistentArcException ex) {
				//TODO add exception handling code
			} catch (BadAttributeListException ex) {
				//TODO add exception handling code
			}
        }
    }//GEN-LAST:event_attrDialogButtonActionPerformed

    private void attributeDComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_attributeDComboBoxActionPerformed
        ArcBean tempArc = arcRows.get(selectedRowID);
        int attrVal = tempArc.getAttribute(attributeDComboBox.getSelectedItem().toString()).getValue();
        attributeDValueText.setText(String.valueOf(attrVal));
    }//GEN-LAST:event_attributeDComboBoxActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton arcButton;
    private javax.swing.JButton arcDialogButton;
    private javax.swing.JScrollPane arcScrollPanel;
    private javax.swing.JTable arcsTable;
    private javax.swing.JButton attrDialogButton;
    private javax.swing.JComboBox attributeDComboBox;
    private javax.swing.JLabel attributeDLabel;
    private javax.swing.JLabel attributeDValueLabel;
    private javax.swing.JTextField attributeDValueText;
    private javax.swing.JDialog attributeDialog;
    private javax.swing.JDialog createArcDialog;
    private javax.swing.JComboBox fromNodeComboBox;
    private javax.swing.JLabel fromNodeLabel;
    private javax.swing.JComboBox toNodeComboBox;
    private javax.swing.JLabel toNodeLabel;
    // End of variables declaration//GEN-END:variables
    private Controller controller;

    public void setController(Controller controller) {
        this.controller = controller;
    }

    public void loadGraph(GraphBean graph) {
        this.graph = graph;
        tArcModel = (DefaultTableModel) arcsTable.getModel();
        this.syncOnLoad();
        this.setTableProperties();
    }

    private void setTableProperties() {
        tArcModel = (DefaultTableModel) arcsTable.getModel();
        int vColIndex = 3;
        TableColumn tcol3 = arcsTable.getColumnModel().getColumn(vColIndex);
        tcol3.setCellRenderer(new ButtonRenderer());
        tcol3.setCellEditor(new ButtonEditor(new JCheckBox(), ATTRIBUTE_ID));

        vColIndex = 4;
        TableColumn tcol4 = arcsTable.getColumnModel().getColumn(vColIndex);
        tcol4.setCellRenderer(new ButtonRenderer());
        tcol4.setCellEditor(new ButtonEditor(new JCheckBox(), DELETE_ID));
    }

    private void syncOnLoad() {
        tArcModel = (DefaultTableModel) arcsTable.getModel();
        if (graph != null && graph.getArcs().size() > 0) {
            for (ArcBean arc : graph.getArcs()) {
                insertArc(arc);
            }
            Vector nodeNames = new Vector();
            //nodeNames.add(" ");
            for (NodeBean node : graph.getNodes()) {
                nodeNames.add(node.getId());
            }
            this.fromNodeComboBox.setModel(new javax.swing.DefaultComboBoxModel(nodeNames));
            this.toNodeComboBox.setModel(new javax.swing.DefaultComboBoxModel(nodeNames));

        }
    }

    public void insertArc(ArcBean arc) {
        tArcModel.insertRow(rowcount, new Object[]{"" + (rowcount + 1), arc.getFromId(), arc.getToId(), "Modify", "X"});
        arcRows.put(rowcount, arc);

        rowcount++;
    }

    public void deleteArc(ArcBean arc) {
        TreeMap<Integer, ArcBean> tempArcs = new TreeMap<Integer, ArcBean>();
        Integer tempRowCount = 0;
        for (int a = 0; a < arcRows.size(); a++) {
            if (arc == arcRows.get(a)) {
                selectedRowID = a;
            }
        }
        tArcModel.removeRow(selectedRowID);
        for (int i = 0; i < rowcount; i++) {
            if (i != selectedRowID) {
                tempArcs.put(tempRowCount, arcRows.get(i));
                tArcModel.setValueAt(tempRowCount + 1, tempRowCount, 0);
                tempRowCount++;
            }
        }
        arcRows = tempArcs;
        rowcount--;
    }

    public void addArcAttribute(String name, Integer val) {
        arcAttributes.put(name, val);        
        attributeDComboBox.setModel(new javax.swing.DefaultComboBoxModel(arcAttributes.keySet().toArray()));
    }

    public void removeArcAttribute(String name) {
        Iterator<String> it = arcAttributes.keySet().iterator();
        while (it.hasNext()) {
            if (it.next().equalsIgnoreCase(name)) {
                it.remove();
            }
        }        
        attributeDComboBox.setModel(new javax.swing.DefaultComboBoxModel(arcAttributes.keySet().toArray()));
    }

    private class ButtonRenderer extends JButton implements TableCellRenderer {

        public ButtonRenderer() {
            setOpaque(true);
        }

        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {
            if (isSelected) {
                setForeground(table.getSelectionForeground());
                setBackground(table.getSelectionBackground());
            } else {
                setForeground(table.getForeground());
                setBackground(UIManager.getColor("Button.background"));
            }
            setText((value == null) ? "" : value.toString());
            return this;
        }
    }

    /**
     * @version 1.0 11/09/98
     */
    private class ButtonEditor extends DefaultCellEditor {

        protected JButton button;
        private String label;
        private boolean isPushed;
        private int buttonID;

        public ButtonEditor(JCheckBox checkBox, int id) {
            super(checkBox);
            button = new JButton();
            button.setOpaque(true);
            buttonID = id;
            button.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    fireEditingStopped();
                }
            });
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value,
                boolean isSelected, int row, int column) {
            if (isSelected) {
                button.setForeground(table.getSelectionForeground());
                button.setBackground(table.getSelectionBackground());
            } else {
                button.setForeground(table.getForeground());
                button.setBackground(table.getBackground());
            }
            label = (value == null) ? "" : value.toString();
            button.setText(label);
            isPushed = true;
            selectedRowID = row;
            return button;
        }

        @Override
        public Object getCellEditorValue() {
            if (isPushed) {
                if (buttonID == ATTRIBUTE_ID) {
                    ArcBean tempArc = arcRows.get(selectedRowID);
					List<String> attributes = new ArrayList<String>();
					for (Attribute att : graph.getDefaultArcAttributes()) {
						attributes.add(att.getName());
					}
                    attributeDComboBox.setModel(new javax.swing.DefaultComboBoxModel(attributes.toArray()));
                    for (Attribute atr : tempArc.getAttributes()) {
                        if (attributeDComboBox.getSelectedItem() != null && atr.getName().equalsIgnoreCase(attributeDComboBox.getSelectedItem().toString())) {
                            attributeDValueText.setText(((Integer) (atr.getValue())).toString());
                        }
                    }
                    attributeDialog.setVisible(isPushed);
                } else if (buttonID == DELETE_ID) {
                    GraphController gc = controller.getGraphController(graph.getID());
					try {
						gc.deleteArc(arcRows.get(selectedRowID));
					} catch (UnexistentArcException ex) {
						//TODO add exception handling code.
					}
                }
            }
            isPushed = false;
            return new String(label);
        }

        @Override
        public boolean stopCellEditing() {
            isPushed = false;
            return super.stopCellEditing();
        }

        @Override
        protected void fireEditingStopped() {
            try {
                super.fireEditingStopped();
            } catch (Exception e) {
            }
        }
    }
}
